<?php

namespace app\common\logic\meet;

use app\admin\model\Third;
use app\common\model\meet\Config;
use app\common\model\meet\Coupon;
use app\common\model\meet\product\Product;
use app\common\model\meet\Store;
use app\common\model\User;
use EasyWeChat\Factory;
use think\Db;

class Order
{
    protected $error = '';

    public function getOrderData($user_id, $product_id, $product_sku_id, $reservation_time, $coupon_id = 0)
    {
        if (empty($product_id) || empty($reservation_time)) {
            $this->error = __('Parameter %s can not be empty', '');
            return false;
        }

        $product = Product::with(['spec', 'specRel'])->where('id', '=', $product_id)->field('id,store_id,category_id,name,cover_image,images,spec_type,status')->find();

        if (empty($product)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($product->status !== Product::STATUS_NORMAL) {
            $this->error = __('The product has been removed from the shelves');
            return false;
        }

        // 产品sku信息
        $product['product_sku'] = $this->getProductSku($product, $product_sku_id);

        //产品单价
        $product['product_price'] = $product['product_sku']['product_price'];
        //产品押金
        $product['product_deposit'] = $product['product_sku']['product_deposit'];
        //产品总价
        $product['total_price'] = $totalPrice = (float)bcadd($product['product_price'], $product['product_deposit'], 2);

        $coupon_money = 0;
        if ($coupon_id > 0) {
            $coupon_model = new Coupon();
            $coupon_info = $coupon_model->where(['user_id' => $user_id, 'id' => $coupon_id])->find();

            if (empty($coupon_info)) {
                $this->error = __('The coupon does not exist');
                return false;
            }

            if ($coupon_info['status'] != $coupon_model::STATUS_NOT_USE) {
                $this->error = __('This coupon is already in use');
                return false;
            }

            if ($coupon_info['limit'] > $totalPrice) {
                $this->error = __('This coupon does not meet the usage conditions');
                return false;
            }

            if (($coupon_info['end_time'] != 0) && (($coupon_info['end_time']) <= time()) && ($coupon_info['start_time'] > time())) {
                $this->error = __('This coupon is currently unavailable for use');
                return false;
            }

            if (($coupon_info['end_time'] != 0) && ($coupon_info['end_time']) <= time()) {
                $this->error = __('This coupon has expired');
                return false;
            }

            $coupon_money = $coupon_info['money'];
        }

        $order_pay_price = bcsub($totalPrice, $coupon_money, 2);
        $order_pay_price = $order_pay_price >= 0 ? $order_pay_price : 0;
        //门店信息
        $store = Store::where('id', '=', $product['store_id'])->field('id,name')->find();

        $user = User::where('id', '=', $user_id)->find();

        return [
            'product_list' => [$product],               // 产品详情
            'order_total_price' => (float)$totalPrice,    // 产品总金额
            'order_pay_price' => (float)$order_pay_price,  // 实际支付金额
            'coupon_money' => (float)$coupon_money,
            'coupon_id' => $coupon_id,
            'order_deposit' => $product['product_deposit'],
            'reservation_time' => $reservation_time,
            'reservation_time_text' => date('Y-m-d H:i', $reservation_time),
            'store' => $store,
            'user' => [
                'call_name' => $user->nickname ?: '',
                'gender' => $user->gender ?: '',
//                'birthday' => $user->birthday ?: '',
                'mobile' => $user->mobile ?: ''
            ],
            'product_ids' => $product['id']
        ];
    }

    /**
     * 创建订单
     */
    public function createOrder($user_info, $order, $post)
    {
        $order_id = 0;

        Db::startTrans();
        try {

            $model = new \app\common\model\meet\Order();

            $model->save([
                'user_id' => $user_info['id'],
                'nickname' => $user_info['nickname'],
                'call_name' => $post['call_name'],
                'gender' => $post['gender'],
//                'birthday' => $post['birthday'],
                'mobile' => $order['user']['mobile'],
                'order_no' => $model->createOrderNo(),
                'total_price' => $order['order_total_price'],
                'pay_price' => $order['order_pay_price'],
                'order_deposit' => $order['order_deposit'],
                'reservation_time' => $post['reservation_time'],
                'store_id' => $order['store']['id'],
                'store_name' => $order['store']['name'],
                'coupon_id' => $order['coupon_id'],
                'coupon_money' => $order['coupon_money']
            ]);

            // 订单产品列表
            $productList = [];

            foreach ($order['product_list'] as $product) {
                $productList[] = [
                    'user_id' => $user_info['id'],
                    'product_id' => $product['id'],
                    'product_name' => $product['name'],
                    'images' => $product['images'],
                    'spec_type' => $product['spec_type'],
                    'spec_sku_id' => $product['product_sku']['spec_sku_id'],
                    'spec_image' => $product['product_sku']['spec_image'],
                    'product_spec_id' => $product['product_sku']['spec_id'],
                    'product_attr' => $product['product_sku']['product_attr'],
                    'product_price' => $product['product_sku']['product_price'],
                    'product_deposit' => $product['product_sku']['product_deposit'],
                    'product_people_nums' => $product['product_sku']['product_people_nums'],
                    'total_price' => $product['total_price'],
                    'store_id' => $order['store']['id'],
                    'store_name' => $order['store']['name']
                ];
            }

            $model->products()->saveAll($productList);

            $order_id = (int)$model->id;

            if ($order['coupon_id'] > 0) {
                (new Coupon())->save(['status' => Coupon::STATUS_USE, 'use_time' => time()], ['id' => $order['coupon_id']]);
            }

            //更新用户信息
            $update = [];
            if ($user_info['gender'] === '' || $user_info['gender'] === null) {
                $update['gender'] = $post['gender'];
            }

//            if (empty($user_info['birthday'])) {
//                $update['birthday'] = $post['birthday'];
//            }

            if (!empty($update)) {
                (new User())->save($update, ['id' => $user_info['id']]);
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return $order_id;
    }

    public function payOrder($order_id, $notify_url)
    {
        $model = new \app\common\model\meet\Order();

        $order = $model->where('id', '=', $order_id)->find();

        if (empty($order)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order->pay_status == $model::PAY_STATUS_PAYED) {
            $this->error = __('The order has already been paid, please do not pay twice');
            return false;
        }

        if ($order->pay_price <= 0) {
            $this->paySuccess($order, [], 'wxapp');
            return ['status' => 1, 'config' => []];
        }

        $bridge_config = [];

        try {
            $config = Config::getPayConfig();

            $config['notify_url'] = $notify_url;

            $app = Factory::payment($config);

            $openid = Third::where('user_id', '=', $order->user_id)->value('openid');

            if (empty($openid)) {
                throw new \Exception(__('Operation failed'));
            }

            $response = $app->order->unify([
                'body' => $order['order_no'],
                'out_trade_no' => $order['order_no'],
                'total_fee' => $order['pay_price'] * 100,
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $openid,
                'notify_url' => $notify_url
            ]);

            //调用支付失败
            if ($response["return_code"] === 'FAIL') {
                throw new \Exception($response["return_msg"]);
            }

            if ($response["result_code"] === 'FAIL') {
                throw new \Exception($response["err_code_des"]);
            }

            $bridge_config = $app->jssdk->bridgeConfig($response['prepay_id'], false);

            //计划任务-取消订单
            $auto_close = Config::getConfigByName('meet_order_auto_close')['value'];
            $cronLogic = new Cron();
            $cronLogic->addCron('预约-取消订单', 'CronMeetOrderCancel', time() + (($auto_close ?: 5) * 60), $order['id']);

        } catch (\Exception $e) {
            $this->error = $e->getMessage();
            return false;
        }

        return ['status' => 2, 'config' => $bridge_config];
    }

    public function paySuccess($order, $update, $pay_method = '')
    {
        $update['order_status'] = \app\common\model\meet\Order::ORDER_STATUS_PAYED;
        $update['pay_status'] = \app\common\model\meet\Order::PAY_STATUS_PAYED;
        $update['pay_time'] = time();
        $update['pay_method'] = $pay_method;

        $order->save($update);

        $cronLogic = new Cron();
        //计划任务-完成订单
//        $hours = Config::getConfigByName('meet_order_complete')['value'];
//        if ($hours > 0) {
//            $cronLogic->addCron('预约-完成订单', 'CronMeetOrderComplete', $order['reservation_time'] + (($hours ?: 2) * 3600), $order['id']);
//        }

        //计划任务-下单成功发送消息
        $cronLogic->addCron('预约-下单成功发送消息', 'CronMeetOrderMessage', 0, $order['id']);

        //支付成功删除定时取消任务
        (new \app\common\model\meet\Cron())->where(['event' => 'CronMeetOrderCancel', 'relate_id' => $order['id']])->delete();
    }

    /**
     * 取消订单
     */
    public function cancelOrder($order_id)
    {
        $model = new \app\common\model\meet\Order();

        $order = $model->where('id', '=', $order_id)->find();

        if (empty($order)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order->pay_status == $model::PAY_STATUS_PAYED) {
            $this->error = __('Paid orders cannot be cancelled');
            return false;
        }

        if ($order->order_status == $model::ORDER_STATUS_CANCEL) {
            $this->error = __('The order has been cancelled, please do not repeat the operation');
            return false;
        }

        $order->save([
            'order_status' => $model::ORDER_STATUS_CANCEL
        ]);

        if ($order['coupon_id'] > 0) {
            (new Coupon())->save(['status' => Coupon::STATUS_NOT_USE, 'use_time' => 0], ['id' => $order['coupon_id']]);
        }

        return true;
    }

    /**
     * 订单-进行中
     */
    public function progressOrder($order_id)
    {
        $model = new \app\common\model\meet\Order();

        $order = $model->where('id', '=', $order_id)->find();

        if (empty($order)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order->order_status < $model::ORDER_STATUS_PAYED || $order->order_status >= $model::ORDER_STATUS_PROGRESS) {
            $this->error = __('Operation failed');
            return false;
        }

        $order->save([
            'order_status' => $model::ORDER_STATUS_PROGRESS
        ]);

        return true;
    }

    /**
     * 完成订单
     */
    public function completeOrder($order_id)
    {
        $model = new \app\common\model\meet\Order();

        $order = $model->where('id', '=', $order_id)->find();

        if (empty($order)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order->order_status < $model::ORDER_STATUS_PAYED || $order->order_status == $model::ORDER_STATUS_FINISHED) {
            $this->error = __('Operation failed');
            return false;
        }

//        if ($order->order_status != $model::ORDER_STATUS_PROGRESS) {
//            $this->error = __('Shooting has not started and cannot be operated');
//            return false;
//        }

        //退还押金
//        $res = $this->refundDeposit($order);
//
//        if (!$res) {
//            return false;
//        }

        $order->save([
            'order_status' => $model::ORDER_STATUS_FINISHED
        ]);

        return true;
    }

    /**
     * 申请退款
     */
    public function refundOrder($order_id)
    {
        $model = new \app\common\model\meet\Order();

        $order = $model->where('id', '=', $order_id)->find();

        if (empty($order)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order['pay_status'] == $model::PAY_STATUS_UNPAY) {
            $this->error = __('Unable to refund (this order has not been paid)');
            return false;
        }

        if ($order['pay_status'] == $model::PAY_STATUS_REFUND) {
            $this->error = __('Refunded, please do not resubmit');
            return false;
        }

        if ($order['order_status'] != $model::ORDER_STATUS_PAYED) {
            $this->error = __('Unable to refund (this order has already been used)');
            return false;
        }

        if ($order['reservation_time'] < time()) {
            $this->error = __('No refunds are available');
            return false;
        }

        $store = Store::where('id', $order['store_id'])->find();

        if ($store['early_refund'] > 0) {
            if (($order['reservation_time'] - time()) < ($store['early_refund'] * 60)) {
                $this->error = __('Unable to refund (beyond the refund period)');
                return false;
            }
        }

        Db::startTrans();
        try {
            $refund_number = $model->createRefundNo();

            $update = [
                'refund_number' => $refund_number,
                'refund_time' => time(),
                'pay_status' => $model::PAY_STATUS_REFUND,
                'order_status' => $model::ORDER_STATUS_CANCEL
            ];

            if ($order['pay_price'] > 0) {
                $config = Config::getPayConfig();

                $config['notify_url'] = '';

                $app = Factory::payment($config);

                $refund_money = $order['pay_price'];
                if ($store['refund_handle_fee'] > 0) {
                    $total_fee = (int)(string)($order['pay_price'] * 100);//订单支付金额
                    $refund_money -= ($order['pay_price'] * ($store['refund_handle_fee'] / 100));
                    $refund_fee = (int)(string)($refund_money * 100);//退款金额
                } else {
                    $total_fee = (int)(string)($order['pay_price'] * 100);//订单支付金额
                    $refund_fee = (int)(string)($refund_money * 100);//退款金额
                }

                $result = $app->refund->byTransactionId($order['transaction_id'], $refund_number, $total_fee, $refund_fee, ['refund_desc' => '预约订单退款']);

                if ($result["return_code"] === 'FAIL') {
                    throw new \Exception($result["return_msg"]);
                }

                if ($result["result_code"] === 'FAIL') {
                    throw new \Exception($result["err_code_des"]);
                }

                $update['refund_transaction_id'] = $result['refund_id'];
                $update['refund_money'] = $refund_money;
            }

            $order->save($update);

            if ($order['coupon_id'] > 0) {
                (new Coupon())->save(['status' => Coupon::STATUS_NOT_USE, 'use_time' => 0], ['id' => $order['coupon_id']]);
            }

            //删除计划任务
//            (new \app\common\model\meet\Cron())->where(['event' => 'CronMeetOrderComplete', 'relate_id' => $order['id']])->delete();

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    /**
     * 退还押金
     * @param $order
     * @return bool
     */
    public function refundDeposit($order)
    {
        $order_model = new \app\common\model\meet\Order();
        if ($order['order_status'] < $order_model::ORDER_STATUS_PAYED) {
            $this->error = __('If the order is not paid, no deposit will be refunded');
            return false;
        }

        if ($order['order_status'] == $order_model::ORDER_STATUS_FINISHED) {
            $this->error = __('The order has been completed and the deposit cannot be refunded');
            return false;
        }

        if ($order['is_refund_deposit'] == $order_model::IS_REFUND_DEPOSIT_YES) {
            $this->error = __('The deposit has been refunded for the order, please do not repeat the operation');
            return false;
        }

        if ($order['order_deposit'] <= 0) {
            $this->error = __('There is no deposit for orders and no deposit can be refunded');
        }

        try {
            $config = Config::getPayConfig();

            $config['notify_url'] = '';

            $app = Factory::payment($config);

            $total_fee = (int)(string)($order['pay_price'] * 100);//订单支付金额
            $refund_fee = (int)(string)($order['order_deposit'] * 100);//退款金额

            $refund_number = (new \app\common\model\meet\Order())->createRefundNo();

            $result = $app->refund->byTransactionId($order['transaction_id'], $refund_number, $total_fee, $refund_fee, ['refund_desc' => '押金退款']);

            if ($result["return_code"] === 'FAIL') {
                $this->error = $result["return_msg"];
                return false;
            }

            if ($result["result_code"] === 'FAIL') {
                $this->error = $result["err_code_des"];
                return false;
            }

            $order->save([
                'is_refund_deposit' => \app\common\model\meet\Order::IS_REFUND_DEPOSIT_YES,
                'refund_number' => $refund_number,
                'refund_time' => time(),
                'refund_transaction_id' => $result['refund_id'],
                'refund_money' => $order['order_deposit']
            ]);
        } catch (\Exception $e) {
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    /**
     * 产品多规格信息
     */
    public function getProductSku($product, $product_sku_id)
    {
        $productSkuData = array_column($product['spec'], null, 'spec_sku_id');

        if (!isset($productSkuData[$product_sku_id])) {
            return false;
        }
        $product_sku = $productSkuData[$product_sku_id];
        // 多规格文字内容
        $product_sku['product_attr'] = '';
        if ($product['spec_type'] === '20') {
            $attrs = explode('_', $product_sku['spec_sku_id']);
            $spec_rel = array_column($product['specRel'], null, 'id');

            foreach ($attrs as $specValueId) {
                $product_sku['product_attr'] .= $spec_rel[$specValueId]['spec']['spec_name'] . ':'
                    . $spec_rel[$specValueId]['spec_value'] . '; ';
            }
        }

        $image_arr = explode(',', $product['images']);


        //这里格式化 展示图片
        $product_sku['img_show'] = $product_sku['spec_image'] == '' ? cdnurl($image_arr[0], true) : cdnurl($product_sku['spec_image'], true);

        $product_sku['spec_image'] = $product_sku['spec_image'] == '' ? $image_arr[0] : $product_sku['spec_image'];
        return $product_sku;
    }

    public function getError()
    {
        return $this->error;
    }
}